{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "axgaosQDxyM4"
      },
      "source": [
        "# How To Build An AI Agent With Claude 3.5 Sonnet, LlamaIndex and MongoDB"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mongodb-developer/GenAI-Showcase/blob/main/notebooks/agents/how_to_build_ai_agent_claude_3_5_sonnet_llamaindex_mongodb.ipynb)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l7PuZzJDwAWr"
      },
      "source": [
        "## Set Up Libraries"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jwCBOcXw_nBh",
        "outputId": "cc82157d-91b3-4e22-c0e2-af775c20f50b"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m15.4/15.4 MB\u001b[0m \u001b[31m67.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m67.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m8.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m130.8/130.8 kB\u001b[0m \u001b[31m15.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m327.4/327.4 kB\u001b[0m \u001b[31m31.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m64.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m290.4/290.4 kB\u001b[0m \u001b[31m30.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m9.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.2/49.2 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m669.1/669.1 kB\u001b[0m \u001b[31m5.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m307.7/307.7 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m862.7/862.7 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m318.9/318.9 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m44.6/44.6 kB\u001b[0m \u001b[31m1.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m43.9/43.9 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
            "  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.5/62.5 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m853.2/853.2 kB\u001b[0m \u001b[31m18.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.3/21.3 MB\u001b[0m \u001b[31m61.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Building wheel for nomic (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m547.8/547.8 kB\u001b[0m \u001b[31m8.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.8/40.8 MB\u001b[0m \u001b[31m13.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m116.3/116.3 kB\u001b[0m \u001b[31m14.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m64.9/64.9 kB\u001b[0m \u001b[31m7.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.1/194.1 kB\u001b[0m \u001b[31m21.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m134.8/134.8 kB\u001b[0m \u001b[31m16.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
            "cudf-cu12 24.4.1 requires pyarrow<15.0.0a0,>=14.0.1, but you have pyarrow 16.1.0 which is incompatible.\n",
            "google-colab 1.0.0 requires requests==2.31.0, but you have requests 2.32.3 which is incompatible.\n",
            "ibis-framework 8.0.0 requires pyarrow<16,>=2, but you have pyarrow 16.1.0 which is incompatible.\u001b[0m\u001b[31m\n",
            "\u001b[0m"
          ]
        }
      ],
      "source": [
        "!pip install --quiet llama-index  # main llamaindex libary\n",
        "!pip install --quiet llama-index-vector-stores-mongodb # mongodb vector database\n",
        "!pip install --quiet llama-index-llms-anthropic # anthropic llm provider\n",
        "!pip install --quiet llama-index-embeddings-openai # openai embedding provider\n",
        "!pip install --quiet pymongo pandas datasets # others"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "siDlNHlKwGgE"
      },
      "source": [
        "## Set Up Environment Variables"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "id": "2sxMs_60wNPD"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "\n",
        "# WARNING: Never commit API keys or sensitive information to public repositories\n",
        "\n",
        "os.environ[\"ANTHROPIC_API_KEY\"] = \"\"\n",
        "os.environ[\"HF_TOKEN\"] = \"\"\n",
        "os.environ[\"OPENAI_API_KEY\"] = \"\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "osmgS5DbxD7h"
      },
      "source": [
        "## Configure LLMs and Embedding Models"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "id": "qz0tqiaswbKW"
      },
      "outputs": [],
      "source": [
        "from llama_index.core import Settings\n",
        "from llama_index.embeddings.openai import OpenAIEmbedding\n",
        "from llama_index.llms.anthropic import Anthropic\n",
        "\n",
        "llm = Anthropic(model=\"claude-3-5-sonnet-20240620\")\n",
        "\n",
        "embed_model = OpenAIEmbedding(\n",
        "    model=\"text-embedding-3-small\",\n",
        "    dimensions=256,\n",
        "    embed_batch_size=10,\n",
        "    openai_api_key=os.environ[\"OPENAI_API_KEY\"],\n",
        ")\n",
        "\n",
        "Settings.embed_model = embed_model\n",
        "Settings.llm = llm"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OwX4bbG2xeHG"
      },
      "source": [
        "## Data Loading"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 759
        },
        "id": "1MWkFKGy__ut",
        "outputId": "4ac81899-383c-4732-9068-73779f42486e"
      },
      "outputs": [
        {
          "data": {
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "dataframe",
              "variable_name": "dataset_df"
            },
            "text/html": [
              "\n",
              "  <div id=\"df-33b374c2-5c60-4789-94fa-f5bd061cbd62\" class=\"colab-df-container\">\n",
              "    <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>_id</th>\n",
              "      <th>listing_url</th>\n",
              "      <th>name</th>\n",
              "      <th>summary</th>\n",
              "      <th>space</th>\n",
              "      <th>description</th>\n",
              "      <th>neighborhood_overview</th>\n",
              "      <th>notes</th>\n",
              "      <th>transit</th>\n",
              "      <th>access</th>\n",
              "      <th>...</th>\n",
              "      <th>images</th>\n",
              "      <th>host</th>\n",
              "      <th>address</th>\n",
              "      <th>availability</th>\n",
              "      <th>review_scores</th>\n",
              "      <th>reviews</th>\n",
              "      <th>weekly_price</th>\n",
              "      <th>monthly_price</th>\n",
              "      <th>text_embeddings</th>\n",
              "      <th>image_embeddings</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>10006546</td>\n",
              "      <td>https://www.airbnb.com/rooms/10006546</td>\n",
              "      <td>Ribeira Charming Duplex</td>\n",
              "      <td>Fantastic duplex apartment with three bedrooms...</td>\n",
              "      <td>Privileged views of the Douro River and Ribeir...</td>\n",
              "      <td>Fantastic duplex apartment with three bedrooms...</td>\n",
              "      <td>In the neighborhood of the river, you can find...</td>\n",
              "      <td>Lose yourself in the narrow streets and stairc...</td>\n",
              "      <td>Transport: • Metro station and S. Bento railwa...</td>\n",
              "      <td>We are always available to help guests. The ho...</td>\n",
              "      <td>...</td>\n",
              "      <td>{'thumbnail_url': '', 'medium_url': '', 'pictu...</td>\n",
              "      <td>{'host_id': '51399391', 'host_url': 'https://w...</td>\n",
              "      <td>{'street': 'Porto, Porto, Portugal', 'suburb':...</td>\n",
              "      <td>{'availability_30': 28, 'availability_60': 47,...</td>\n",
              "      <td>{'review_scores_accuracy': 9, 'review_scores_c...</td>\n",
              "      <td>[{'_id': '58663741', 'date': 2016-01-03 05:00:...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>[0.0123710884, -0.0180913936, -0.016843712, -0...</td>\n",
              "      <td>[-0.1302358955, 0.1534578055, 0.0199299306, -0...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>10021707</td>\n",
              "      <td>https://www.airbnb.com/rooms/10021707</td>\n",
              "      <td>Private Room in Bushwick</td>\n",
              "      <td>Here exists a very cozy room for rent in a sha...</td>\n",
              "      <td></td>\n",
              "      <td>Here exists a very cozy room for rent in a sha...</td>\n",
              "      <td></td>\n",
              "      <td></td>\n",
              "      <td></td>\n",
              "      <td></td>\n",
              "      <td>...</td>\n",
              "      <td>{'thumbnail_url': '', 'medium_url': '', 'pictu...</td>\n",
              "      <td>{'host_id': '11275734', 'host_url': 'https://w...</td>\n",
              "      <td>{'street': 'Brooklyn, NY, United States', 'sub...</td>\n",
              "      <td>{'availability_30': 0, 'availability_60': 0, '...</td>\n",
              "      <td>{'review_scores_accuracy': 10, 'review_scores_...</td>\n",
              "      <td>[{'_id': '61050713', 'date': 2016-01-31 05:00:...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>[0.0153845912, -0.0348115042, -0.0093448907, 0...</td>\n",
              "      <td>[0.0340401195, 0.1742489338, -0.1572628617, 0....</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>1001265</td>\n",
              "      <td>https://www.airbnb.com/rooms/1001265</td>\n",
              "      <td>Ocean View Waikiki Marina w/prkg</td>\n",
              "      <td>A short distance from Honolulu's billion dolla...</td>\n",
              "      <td>Great studio located on Ala Moana across the s...</td>\n",
              "      <td>A short distance from Honolulu's billion dolla...</td>\n",
              "      <td>You can breath ocean as well as aloha.</td>\n",
              "      <td></td>\n",
              "      <td>Honolulu does have a very good air conditioned...</td>\n",
              "      <td>Pool, hot tub and tennis</td>\n",
              "      <td>...</td>\n",
              "      <td>{'thumbnail_url': '', 'medium_url': '', 'pictu...</td>\n",
              "      <td>{'host_id': '5448114', 'host_url': 'https://ww...</td>\n",
              "      <td>{'street': 'Honolulu, HI, United States', 'sub...</td>\n",
              "      <td>{'availability_30': 16, 'availability_60': 46,...</td>\n",
              "      <td>{'review_scores_accuracy': 9, 'review_scores_c...</td>\n",
              "      <td>[{'_id': '4765259', 'date': 2013-05-24 04:00:0...</td>\n",
              "      <td>650.0</td>\n",
              "      <td>2150.0</td>\n",
              "      <td>[-0.0400562622, -0.0405789167, 0.000644172, 0....</td>\n",
              "      <td>[-0.1640156209, 0.1256971657, 0.6594450474, -0...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>10009999</td>\n",
              "      <td>https://www.airbnb.com/rooms/10009999</td>\n",
              "      <td>Horto flat with small garden</td>\n",
              "      <td>One bedroom + sofa-bed in quiet and bucolic ne...</td>\n",
              "      <td>Lovely one bedroom + sofa-bed in the living ro...</td>\n",
              "      <td>One bedroom + sofa-bed in quiet and bucolic ne...</td>\n",
              "      <td>This charming ground floor flat is located in ...</td>\n",
              "      <td>There´s a table in the living room now, that d...</td>\n",
              "      <td>Easy access to transport (bus, taxi, car) and ...</td>\n",
              "      <td></td>\n",
              "      <td>...</td>\n",
              "      <td>{'thumbnail_url': '', 'medium_url': '', 'pictu...</td>\n",
              "      <td>{'host_id': '1282196', 'host_url': 'https://ww...</td>\n",
              "      <td>{'street': 'Rio de Janeiro, Rio de Janeiro, Br...</td>\n",
              "      <td>{'availability_30': 0, 'availability_60': 0, '...</td>\n",
              "      <td>{'review_scores_accuracy': None, 'review_score...</td>\n",
              "      <td>[]</td>\n",
              "      <td>1492.0</td>\n",
              "      <td>4849.0</td>\n",
              "      <td>[-0.063234821, 0.0017937823, -0.0243996996, -0...</td>\n",
              "      <td>[-0.1292964518, 0.037789464, 0.2443587631, 0.0...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>10047964</td>\n",
              "      <td>https://www.airbnb.com/rooms/10047964</td>\n",
              "      <td>Charming Flat in Downtown Moda</td>\n",
              "      <td>Fully furnished 3+1 flat decorated with vintag...</td>\n",
              "      <td>The apartment is composed of 1 big bedroom wit...</td>\n",
              "      <td>Fully furnished 3+1 flat decorated with vintag...</td>\n",
              "      <td>With its diversity Moda- Kadikoy is one of the...</td>\n",
              "      <td></td>\n",
              "      <td></td>\n",
              "      <td></td>\n",
              "      <td>...</td>\n",
              "      <td>{'thumbnail_url': '', 'medium_url': '', 'pictu...</td>\n",
              "      <td>{'host_id': '1241644', 'host_url': 'https://ww...</td>\n",
              "      <td>{'street': 'Kadıköy, İstanbul, Turkey', 'subur...</td>\n",
              "      <td>{'availability_30': 27, 'availability_60': 57,...</td>\n",
              "      <td>{'review_scores_accuracy': 10, 'review_scores_...</td>\n",
              "      <td>[{'_id': '68162172', 'date': 2016-04-02 04:00:...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>[0.023723349, 0.0064210771, -0.0339970738, -0....</td>\n",
              "      <td>[-0.1006749049, 0.4022984803, -0.1821258366, 0...</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "<p>5 rows × 43 columns</p>\n",
              "</div>\n",
              "    <div class=\"colab-df-buttons\">\n",
              "\n",
              "  <div class=\"colab-df-container\">\n",
              "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-33b374c2-5c60-4789-94fa-f5bd061cbd62')\"\n",
              "            title=\"Convert this dataframe to an interactive table.\"\n",
              "            style=\"display:none;\">\n",
              "\n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
              "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
              "  </svg>\n",
              "    </button>\n",
              "\n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    .colab-df-buttons div {\n",
              "      margin-bottom: 4px;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "    <script>\n",
              "      const buttonEl =\n",
              "        document.querySelector('#df-33b374c2-5c60-4789-94fa-f5bd061cbd62 button.colab-df-convert');\n",
              "      buttonEl.style.display =\n",
              "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "      async function convertToInteractive(key) {\n",
              "        const element = document.querySelector('#df-33b374c2-5c60-4789-94fa-f5bd061cbd62');\n",
              "        const dataTable =\n",
              "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                    [key], {});\n",
              "        if (!dataTable) return;\n",
              "\n",
              "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "          + ' to learn more about interactive tables.';\n",
              "        element.innerHTML = '';\n",
              "        dataTable['output_type'] = 'display_data';\n",
              "        await google.colab.output.renderOutput(dataTable, element);\n",
              "        const docLink = document.createElement('div');\n",
              "        docLink.innerHTML = docLinkHtml;\n",
              "        element.appendChild(docLink);\n",
              "      }\n",
              "    </script>\n",
              "  </div>\n",
              "\n",
              "\n",
              "<div id=\"df-e327997a-430a-4814-8211-261c73208b9b\">\n",
              "  <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-e327997a-430a-4814-8211-261c73208b9b')\"\n",
              "            title=\"Suggest charts\"\n",
              "            style=\"display:none;\">\n",
              "\n",
              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "     width=\"24px\">\n",
              "    <g>\n",
              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
              "    </g>\n",
              "</svg>\n",
              "  </button>\n",
              "\n",
              "<style>\n",
              "  .colab-df-quickchart {\n",
              "      --bg-color: #E8F0FE;\n",
              "      --fill-color: #1967D2;\n",
              "      --hover-bg-color: #E2EBFA;\n",
              "      --hover-fill-color: #174EA6;\n",
              "      --disabled-fill-color: #AAA;\n",
              "      --disabled-bg-color: #DDD;\n",
              "  }\n",
              "\n",
              "  [theme=dark] .colab-df-quickchart {\n",
              "      --bg-color: #3B4455;\n",
              "      --fill-color: #D2E3FC;\n",
              "      --hover-bg-color: #434B5C;\n",
              "      --hover-fill-color: #FFFFFF;\n",
              "      --disabled-bg-color: #3B4455;\n",
              "      --disabled-fill-color: #666;\n",
              "  }\n",
              "\n",
              "  .colab-df-quickchart {\n",
              "    background-color: var(--bg-color);\n",
              "    border: none;\n",
              "    border-radius: 50%;\n",
              "    cursor: pointer;\n",
              "    display: none;\n",
              "    fill: var(--fill-color);\n",
              "    height: 32px;\n",
              "    padding: 0;\n",
              "    width: 32px;\n",
              "  }\n",
              "\n",
              "  .colab-df-quickchart:hover {\n",
              "    background-color: var(--hover-bg-color);\n",
              "    box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "    fill: var(--button-hover-fill-color);\n",
              "  }\n",
              "\n",
              "  .colab-df-quickchart-complete:disabled,\n",
              "  .colab-df-quickchart-complete:disabled:hover {\n",
              "    background-color: var(--disabled-bg-color);\n",
              "    fill: var(--disabled-fill-color);\n",
              "    box-shadow: none;\n",
              "  }\n",
              "\n",
              "  .colab-df-spinner {\n",
              "    border: 2px solid var(--fill-color);\n",
              "    border-color: transparent;\n",
              "    border-bottom-color: var(--fill-color);\n",
              "    animation:\n",
              "      spin 1s steps(1) infinite;\n",
              "  }\n",
              "\n",
              "  @keyframes spin {\n",
              "    0% {\n",
              "      border-color: transparent;\n",
              "      border-bottom-color: var(--fill-color);\n",
              "      border-left-color: var(--fill-color);\n",
              "    }\n",
              "    20% {\n",
              "      border-color: transparent;\n",
              "      border-left-color: var(--fill-color);\n",
              "      border-top-color: var(--fill-color);\n",
              "    }\n",
              "    30% {\n",
              "      border-color: transparent;\n",
              "      border-left-color: var(--fill-color);\n",
              "      border-top-color: var(--fill-color);\n",
              "      border-right-color: var(--fill-color);\n",
              "    }\n",
              "    40% {\n",
              "      border-color: transparent;\n",
              "      border-right-color: var(--fill-color);\n",
              "      border-top-color: var(--fill-color);\n",
              "    }\n",
              "    60% {\n",
              "      border-color: transparent;\n",
              "      border-right-color: var(--fill-color);\n",
              "    }\n",
              "    80% {\n",
              "      border-color: transparent;\n",
              "      border-right-color: var(--fill-color);\n",
              "      border-bottom-color: var(--fill-color);\n",
              "    }\n",
              "    90% {\n",
              "      border-color: transparent;\n",
              "      border-bottom-color: var(--fill-color);\n",
              "    }\n",
              "  }\n",
              "</style>\n",
              "\n",
              "  <script>\n",
              "    async function quickchart(key) {\n",
              "      const quickchartButtonEl =\n",
              "        document.querySelector('#' + key + ' button');\n",
              "      quickchartButtonEl.disabled = true;  // To prevent multiple clicks.\n",
              "      quickchartButtonEl.classList.add('colab-df-spinner');\n",
              "      try {\n",
              "        const charts = await google.colab.kernel.invokeFunction(\n",
              "            'suggestCharts', [key], {});\n",
              "      } catch (error) {\n",
              "        console.error('Error during call to suggestCharts:', error);\n",
              "      }\n",
              "      quickchartButtonEl.classList.remove('colab-df-spinner');\n",
              "      quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",
              "    }\n",
              "    (() => {\n",
              "      let quickchartButtonEl =\n",
              "        document.querySelector('#df-e327997a-430a-4814-8211-261c73208b9b button');\n",
              "      quickchartButtonEl.style.display =\n",
              "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "    })();\n",
              "  </script>\n",
              "</div>\n",
              "\n",
              "    </div>\n",
              "  </div>\n"
            ],
            "text/plain": [
              "        _id                            listing_url  \\\n",
              "0  10006546  https://www.airbnb.com/rooms/10006546   \n",
              "1  10021707  https://www.airbnb.com/rooms/10021707   \n",
              "2   1001265   https://www.airbnb.com/rooms/1001265   \n",
              "3  10009999  https://www.airbnb.com/rooms/10009999   \n",
              "4  10047964  https://www.airbnb.com/rooms/10047964   \n",
              "\n",
              "                               name  \\\n",
              "0           Ribeira Charming Duplex   \n",
              "1          Private Room in Bushwick   \n",
              "2  Ocean View Waikiki Marina w/prkg   \n",
              "3      Horto flat with small garden   \n",
              "4    Charming Flat in Downtown Moda   \n",
              "\n",
              "                                             summary  \\\n",
              "0  Fantastic duplex apartment with three bedrooms...   \n",
              "1  Here exists a very cozy room for rent in a sha...   \n",
              "2  A short distance from Honolulu's billion dolla...   \n",
              "3  One bedroom + sofa-bed in quiet and bucolic ne...   \n",
              "4  Fully furnished 3+1 flat decorated with vintag...   \n",
              "\n",
              "                                               space  \\\n",
              "0  Privileged views of the Douro River and Ribeir...   \n",
              "1                                                      \n",
              "2  Great studio located on Ala Moana across the s...   \n",
              "3  Lovely one bedroom + sofa-bed in the living ro...   \n",
              "4  The apartment is composed of 1 big bedroom wit...   \n",
              "\n",
              "                                         description  \\\n",
              "0  Fantastic duplex apartment with three bedrooms...   \n",
              "1  Here exists a very cozy room for rent in a sha...   \n",
              "2  A short distance from Honolulu's billion dolla...   \n",
              "3  One bedroom + sofa-bed in quiet and bucolic ne...   \n",
              "4  Fully furnished 3+1 flat decorated with vintag...   \n",
              "\n",
              "                               neighborhood_overview  \\\n",
              "0  In the neighborhood of the river, you can find...   \n",
              "1                                                      \n",
              "2             You can breath ocean as well as aloha.   \n",
              "3  This charming ground floor flat is located in ...   \n",
              "4  With its diversity Moda- Kadikoy is one of the...   \n",
              "\n",
              "                                               notes  \\\n",
              "0  Lose yourself in the narrow streets and stairc...   \n",
              "1                                                      \n",
              "2                                                      \n",
              "3  There´s a table in the living room now, that d...   \n",
              "4                                                      \n",
              "\n",
              "                                             transit  \\\n",
              "0  Transport: • Metro station and S. Bento railwa...   \n",
              "1                                                      \n",
              "2  Honolulu does have a very good air conditioned...   \n",
              "3  Easy access to transport (bus, taxi, car) and ...   \n",
              "4                                                      \n",
              "\n",
              "                                              access  ...  \\\n",
              "0  We are always available to help guests. The ho...  ...   \n",
              "1                                                     ...   \n",
              "2                           Pool, hot tub and tennis  ...   \n",
              "3                                                     ...   \n",
              "4                                                     ...   \n",
              "\n",
              "                                              images  \\\n",
              "0  {'thumbnail_url': '', 'medium_url': '', 'pictu...   \n",
              "1  {'thumbnail_url': '', 'medium_url': '', 'pictu...   \n",
              "2  {'thumbnail_url': '', 'medium_url': '', 'pictu...   \n",
              "3  {'thumbnail_url': '', 'medium_url': '', 'pictu...   \n",
              "4  {'thumbnail_url': '', 'medium_url': '', 'pictu...   \n",
              "\n",
              "                                                host  \\\n",
              "0  {'host_id': '51399391', 'host_url': 'https://w...   \n",
              "1  {'host_id': '11275734', 'host_url': 'https://w...   \n",
              "2  {'host_id': '5448114', 'host_url': 'https://ww...   \n",
              "3  {'host_id': '1282196', 'host_url': 'https://ww...   \n",
              "4  {'host_id': '1241644', 'host_url': 'https://ww...   \n",
              "\n",
              "                                             address  \\\n",
              "0  {'street': 'Porto, Porto, Portugal', 'suburb':...   \n",
              "1  {'street': 'Brooklyn, NY, United States', 'sub...   \n",
              "2  {'street': 'Honolulu, HI, United States', 'sub...   \n",
              "3  {'street': 'Rio de Janeiro, Rio de Janeiro, Br...   \n",
              "4  {'street': 'Kadıköy, İstanbul, Turkey', 'subur...   \n",
              "\n",
              "                                        availability  \\\n",
              "0  {'availability_30': 28, 'availability_60': 47,...   \n",
              "1  {'availability_30': 0, 'availability_60': 0, '...   \n",
              "2  {'availability_30': 16, 'availability_60': 46,...   \n",
              "3  {'availability_30': 0, 'availability_60': 0, '...   \n",
              "4  {'availability_30': 27, 'availability_60': 57,...   \n",
              "\n",
              "                                       review_scores  \\\n",
              "0  {'review_scores_accuracy': 9, 'review_scores_c...   \n",
              "1  {'review_scores_accuracy': 10, 'review_scores_...   \n",
              "2  {'review_scores_accuracy': 9, 'review_scores_c...   \n",
              "3  {'review_scores_accuracy': None, 'review_score...   \n",
              "4  {'review_scores_accuracy': 10, 'review_scores_...   \n",
              "\n",
              "                                             reviews  weekly_price  \\\n",
              "0  [{'_id': '58663741', 'date': 2016-01-03 05:00:...           NaN   \n",
              "1  [{'_id': '61050713', 'date': 2016-01-31 05:00:...           NaN   \n",
              "2  [{'_id': '4765259', 'date': 2013-05-24 04:00:0...         650.0   \n",
              "3                                                 []        1492.0   \n",
              "4  [{'_id': '68162172', 'date': 2016-04-02 04:00:...           NaN   \n",
              "\n",
              "  monthly_price                                    text_embeddings  \\\n",
              "0           NaN  [0.0123710884, -0.0180913936, -0.016843712, -0...   \n",
              "1           NaN  [0.0153845912, -0.0348115042, -0.0093448907, 0...   \n",
              "2        2150.0  [-0.0400562622, -0.0405789167, 0.000644172, 0....   \n",
              "3        4849.0  [-0.063234821, 0.0017937823, -0.0243996996, -0...   \n",
              "4           NaN  [0.023723349, 0.0064210771, -0.0339970738, -0....   \n",
              "\n",
              "                                    image_embeddings  \n",
              "0  [-0.1302358955, 0.1534578055, 0.0199299306, -0...  \n",
              "1  [0.0340401195, 0.1742489338, -0.1572628617, 0....  \n",
              "2  [-0.1640156209, 0.1256971657, 0.6594450474, -0...  \n",
              "3  [-0.1292964518, 0.037789464, 0.2443587631, 0.0...  \n",
              "4  [-0.1006749049, 0.4022984803, -0.1821258366, 0...  \n",
              "\n",
              "[5 rows x 43 columns]"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import pandas as pd\n",
        "from datasets import load_dataset\n",
        "\n",
        "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n",
        "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n",
        "\n",
        "# https://huggingface.co/datasets/MongoDB/airbnb_embeddings\n",
        "dataset = load_dataset(\"MongoDB/airbnb_embeddings\", split=\"train\", streaming=True)\n",
        "dataset = dataset.take(4000)\n",
        "\n",
        "# Convert the dataset to a pandas dataframe\n",
        "dataset_df = pd.DataFrame(dataset)\n",
        "\n",
        "dataset_df.head(5)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "mo8vflfofyr3"
      },
      "outputs": [],
      "source": [
        "# Dataset comes with embeddings created with OpenAI, but we are going to recreate new ones\n",
        "dataset_df = dataset_df.drop(columns=[\"text_embeddings\"])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tlMnDPOfzMK5"
      },
      "source": [
        "## Data Processing"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "AWpooso1Amft",
        "outputId": "4e4e48fa-87f9-4bd0-e604-aac581b2b8bb"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "The LLM sees this: \n",
            " Metadata: listing_url=>https://www.airbnb.com/rooms/10006546\n",
            "name=>Ribeira Charming Duplex\n",
            "summary=>Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character.\n",
            "space=>Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit.\n",
            "description=>Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character. Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit. We are always available to help guests\n",
            "neighborhood_overview=>In the neighborhood of the river, you can find several restaurants as varied flavors, but without forgetting the so traditional northern food. You can also find several bars and pubs to unwind after a day's visit to the magnificent Port. To enjoy the Douro River can board the boats that daily make the ride of six bridges. You can also embark towards Régua, Barca d'Alva, Pinhão, etc and enjoy the Douro Wine Region, World Heritage of Humanity. The Infante's house is a few meters and no doubt it deserves a visit. They abound grocery stores, bakeries, etc. to make your meals. Souvenir shop, wine cellars, etc. to bring some souvenirs.\n",
            "notes=>Lose yourself in the narrow streets and staircases zone, have lunch in pubs and typical restaurants, and find the renovated cafes and shops in town. If you like exercise, rent a bicycle in the area and ride along the river to the sea, where it will enter beautiful beaches and terraces for everyone. The area is safe, find the bus stops 1min and metro line 5min. The bustling nightlife is a 10 min walk, where the streets are filled with people and entertainment for all. But Porto is much more than the historical center, here is modern museums, concert halls, clean and cared for beaches and surf all year round. Walk through the Ponte D. Luis and visit the different Caves of Port wine, where you will enjoy the famous port wine. Porto is a spoken city everywhere in the world as the best to be visited and savored by all ... natural beauty, culture, tradition, river, sea, beach, single people, typical food, and we are among those who best receive tourists, confirm! Come visit us and feel at ho\n",
            "access=>We are always available to help guests. The house is fully available to guests. We are always ready to assist guests. when possible we pick the guests at the airport.  This service transfer have a cost per person. We will also have service \"meal at home\" with a diverse menu and the taste of each. Enjoy the moment!\n",
            "interaction=>Cot - 10 € / night Dog - € 7,5 / night\n",
            "house_rules=>Make the house your home...\n",
            "property_type=>House\n",
            "room_type=>Entire home/apt\n",
            "bed_type=>Real Bed\n",
            "accommodates=>8\n",
            "bedrooms=>3.0\n",
            "beds=>5.0\n",
            "number_of_reviews=>51\n",
            "bathrooms=>1.0\n",
            "amenities=>[\"TV\", \"Cable TV\", \"Wifi\", \"Kitchen\", \"Paid parking off premises\", \"Smoking allowed\", \"Pets allowed\", \"Buzzer/wireless intercom\", \"Heating\", \"Family/kid friendly\", \"Washer\", \"First aid kit\", \"Fire extinguisher\", \"Essentials\", \"Hangers\", \"Hair dryer\", \"Iron\", \"Pack \\u2019n Play/travel crib\", \"Room-darkening shades\", \"Hot water\", \"Bed linens\", \"Extra pillows and blankets\", \"Microwave\", \"Coffee maker\", \"Refrigerator\", \"Dishwasher\", \"Dishes and silverware\", \"Cooking basics\", \"Oven\", \"Stove\", \"Cleaning before checkout\", \"Waterfront\"]\n",
            "price=>80\n",
            "extra_people=>15\n",
            "images=>{\"thumbnail_url\": \"\", \"medium_url\": \"\", \"picture_url\": \"https://a0.muscache.com/im/pictures/e83e702f-ef49-40fb-8fa0-6512d7e26e9b.jpg?aki_policy=large\", \"xl_picture_url\": \"\"}\n",
            "address=>{\"street\": \"Porto, Porto, Portugal\", \"suburb\": \"\", \"government_area\": \"Cedofeita, Ildefonso, S\\u00e9, Miragaia, Nicolau, Vit\\u00f3ria\", \"market\": \"Porto\", \"country\": \"Portugal\", \"country_code\": \"PT\", \"location\": {\"type\": \"Point\", \"coordinates\": [-8.61308, 41.1413], \"is_location_exact\": false}}\n",
            "review_scores=>{\"review_scores_accuracy\": 9, \"review_scores_cleanliness\": 9, \"review_scores_checkin\": 10, \"review_scores_communication\": 10, \"review_scores_location\": 10, \"review_scores_value\": 9, \"review_scores_rating\": 89}\n",
            "weekly_price=>None\n",
            "monthly_price=>None\n",
            "-----\n",
            "Content: Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character. Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit. We are always available to help guests\n",
            "\n",
            "The Embedding model sees this: \n",
            " Metadata: listing_url=>https://www.airbnb.com/rooms/10006546\n",
            "name=>Ribeira Charming Duplex\n",
            "summary=>Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character.\n",
            "space=>Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit.\n",
            "description=>Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character. Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit. We are always available to help guests\n",
            "neighborhood_overview=>In the neighborhood of the river, you can find several restaurants as varied flavors, but without forgetting the so traditional northern food. You can also find several bars and pubs to unwind after a day's visit to the magnificent Port. To enjoy the Douro River can board the boats that daily make the ride of six bridges. You can also embark towards Régua, Barca d'Alva, Pinhão, etc and enjoy the Douro Wine Region, World Heritage of Humanity. The Infante's house is a few meters and no doubt it deserves a visit. They abound grocery stores, bakeries, etc. to make your meals. Souvenir shop, wine cellars, etc. to bring some souvenirs.\n",
            "notes=>Lose yourself in the narrow streets and staircases zone, have lunch in pubs and typical restaurants, and find the renovated cafes and shops in town. If you like exercise, rent a bicycle in the area and ride along the river to the sea, where it will enter beautiful beaches and terraces for everyone. The area is safe, find the bus stops 1min and metro line 5min. The bustling nightlife is a 10 min walk, where the streets are filled with people and entertainment for all. But Porto is much more than the historical center, here is modern museums, concert halls, clean and cared for beaches and surf all year round. Walk through the Ponte D. Luis and visit the different Caves of Port wine, where you will enjoy the famous port wine. Porto is a spoken city everywhere in the world as the best to be visited and savored by all ... natural beauty, culture, tradition, river, sea, beach, single people, typical food, and we are among those who best receive tourists, confirm! Come visit us and feel at ho\n",
            "access=>We are always available to help guests. The house is fully available to guests. We are always ready to assist guests. when possible we pick the guests at the airport.  This service transfer have a cost per person. We will also have service \"meal at home\" with a diverse menu and the taste of each. Enjoy the moment!\n",
            "interaction=>Cot - 10 € / night Dog - € 7,5 / night\n",
            "house_rules=>Make the house your home...\n",
            "property_type=>House\n",
            "room_type=>Entire home/apt\n",
            "bed_type=>Real Bed\n",
            "accommodates=>8\n",
            "bedrooms=>3.0\n",
            "beds=>5.0\n",
            "number_of_reviews=>51\n",
            "bathrooms=>1.0\n",
            "amenities=>[\"TV\", \"Cable TV\", \"Wifi\", \"Kitchen\", \"Paid parking off premises\", \"Smoking allowed\", \"Pets allowed\", \"Buzzer/wireless intercom\", \"Heating\", \"Family/kid friendly\", \"Washer\", \"First aid kit\", \"Fire extinguisher\", \"Essentials\", \"Hangers\", \"Hair dryer\", \"Iron\", \"Pack \\u2019n Play/travel crib\", \"Room-darkening shades\", \"Hot water\", \"Bed linens\", \"Extra pillows and blankets\", \"Microwave\", \"Coffee maker\", \"Refrigerator\", \"Dishwasher\", \"Dishes and silverware\", \"Cooking basics\", \"Oven\", \"Stove\", \"Cleaning before checkout\", \"Waterfront\"]\n",
            "price=>80\n",
            "extra_people=>15\n",
            "images=>{\"thumbnail_url\": \"\", \"medium_url\": \"\", \"picture_url\": \"https://a0.muscache.com/im/pictures/e83e702f-ef49-40fb-8fa0-6512d7e26e9b.jpg?aki_policy=large\", \"xl_picture_url\": \"\"}\n",
            "address=>{\"street\": \"Porto, Porto, Portugal\", \"suburb\": \"\", \"government_area\": \"Cedofeita, Ildefonso, S\\u00e9, Miragaia, Nicolau, Vit\\u00f3ria\", \"market\": \"Porto\", \"country\": \"Portugal\", \"country_code\": \"PT\", \"location\": {\"type\": \"Point\", \"coordinates\": [-8.61308, 41.1413], \"is_location_exact\": false}}\n",
            "review_scores=>{\"review_scores_accuracy\": 9, \"review_scores_cleanliness\": 9, \"review_scores_checkin\": 10, \"review_scores_communication\": 10, \"review_scores_location\": 10, \"review_scores_value\": 9, \"review_scores_rating\": 89}\n",
            "weekly_price=>None\n",
            "monthly_price=>None\n",
            "-----\n",
            "Content: Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character. Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit. We are always available to help guests\n"
          ]
        }
      ],
      "source": [
        "import json\n",
        "\n",
        "from llama_index.core import Document\n",
        "from llama_index.core.schema import MetadataMode\n",
        "\n",
        "# Convert the DataFrame to a JSON string representation\n",
        "documents_json = dataset_df.to_json(orient=\"records\")\n",
        "\n",
        "# Load the JSON string into a Python list of dictionaries\n",
        "documents_list = json.loads(documents_json)\n",
        "\n",
        "llama_documents = []\n",
        "\n",
        "for document in documents_list:\n",
        "    # Value for metadata must be one of (str, int, float, None)\n",
        "    document[\"amenities\"] = json.dumps(document[\"amenities\"])\n",
        "    document[\"images\"] = json.dumps(document[\"images\"])\n",
        "    document[\"host\"] = json.dumps(document[\"host\"])\n",
        "    document[\"address\"] = json.dumps(document[\"address\"])\n",
        "    document[\"availability\"] = json.dumps(document[\"availability\"])\n",
        "    document[\"review_scores\"] = json.dumps(document[\"review_scores\"])\n",
        "    document[\"reviews\"] = json.dumps(document[\"reviews\"])\n",
        "    document[\"image_embeddings\"] = json.dumps(document[\"image_embeddings\"])\n",
        "\n",
        "    # Create a Document object with the text and excluded metadata for llm and embedding models\n",
        "    llama_document = Document(\n",
        "        text=document[\"description\"],\n",
        "        metadata=document,\n",
        "        excluded_llm_metadata_keys=[\n",
        "            \"_id\",\n",
        "            \"transit\",\n",
        "            \"minimum_nights\",\n",
        "            \"maximum_nights\",\n",
        "            \"cancellation_policy\",\n",
        "            \"last_scraped\",\n",
        "            \"calendar_last_scraped\",\n",
        "            \"first_review\",\n",
        "            \"last_review\",\n",
        "            \"security_deposit\",\n",
        "            \"cleaning_fee\",\n",
        "            \"guests_included\",\n",
        "            \"host\",\n",
        "            \"availability\",\n",
        "            \"reviews\",\n",
        "            \"image_embeddings\",\n",
        "        ],\n",
        "        excluded_embed_metadata_keys=[\n",
        "            \"_id\",\n",
        "            \"transit\",\n",
        "            \"minimum_nights\",\n",
        "            \"maximum_nights\",\n",
        "            \"cancellation_policy\",\n",
        "            \"last_scraped\",\n",
        "            \"calendar_last_scraped\",\n",
        "            \"first_review\",\n",
        "            \"last_review\",\n",
        "            \"security_deposit\",\n",
        "            \"cleaning_fee\",\n",
        "            \"guests_included\",\n",
        "            \"host\",\n",
        "            \"availability\",\n",
        "            \"reviews\",\n",
        "            \"image_embeddings\",\n",
        "        ],\n",
        "        metadata_template=\"{key}=>{value}\",\n",
        "        text_template=\"Metadata: {metadata_str}\\n-----\\nContent: {content}\",\n",
        "    )\n",
        "\n",
        "    llama_documents.append(llama_document)\n",
        "\n",
        "# Observing an example of what the LLM and Embedding model receive as input\n",
        "print(\n",
        "    \"\\nThe LLM sees this: \\n\",\n",
        "    llama_documents[0].get_content(metadata_mode=MetadataMode.LLM),\n",
        ")\n",
        "print(\n",
        "    \"\\nThe Embedding model sees this: \\n\",\n",
        "    llama_documents[0].get_content(metadata_mode=MetadataMode.EMBED),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dC7CDZGhzPLn"
      },
      "source": [
        "## Embedding Generation"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "JmCuxyQjAsLs",
        "outputId": "f1d331a6-e8d2-4ef4-d881-8bc87d45c8d1"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "Embedding Progress: 100%|██████████| 4010/4010 [24:59<00:00,  2.67node/s]"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Embedding process completed!\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "source": [
        "from llama_index.core.node_parser import SentenceSplitter\n",
        "from llama_index.core.schema import MetadataMode\n",
        "from tqdm import tqdm\n",
        "\n",
        "# semantic_splitter = SemanticSplitterNodeParser(\n",
        "#     buffer_size=10, breakpoint_percentile_threshold=95, embed_model=embed_model\n",
        "# )\n",
        "\n",
        "base_splitter = SentenceSplitter(chunk_size=5000, chunk_overlap=200)\n",
        "\n",
        "nodes = base_splitter.get_nodes_from_documents(llama_documents)\n",
        "\n",
        "# Progress bar\n",
        "pbar = tqdm(total=len(nodes), desc=\"Embedding Progress\", unit=\"node\")\n",
        "\n",
        "for node in nodes:\n",
        "    node_embedding = embed_model.get_text_embedding(\n",
        "        node.get_content(metadata_mode=MetadataMode.EMBED)\n",
        "    )\n",
        "    node.embedding = node_embedding\n",
        "\n",
        "    # Update the progress bar\n",
        "    pbar.update(1)\n",
        "\n",
        "# Close the progress bar\n",
        "pbar.close()\n",
        "\n",
        "print(\"Embedding process completed!\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UoM9h9JUruSu"
      },
      "source": [
        "## MongoDB Vector Database and Connection Setup\n",
        "\n",
        "MongoDB acts as both an operational and a vector database for the RAG system.\n",
        "MongoDB Atlas specifically provides a database solution that efficiently stores, queries and retrieves vector embeddings.\n",
        "\n",
        "Creating a database and collection within MongoDB is made simple with MongoDB Atlas.\n",
        "\n",
        "1. First, register for a [MongoDB Atlas account](https://www.mongodb.com/cloud/atlas/register). For existing users, sign into MongoDB Atlas.\n",
        "2. [Follow the instructions](https://www.mongodb.com/docs/atlas/tutorial/deploy-free-tier-cluster/). Select Atlas UI as the procedure to deploy your first cluster.\n",
        "3. Create the database: `airbnb`.\n",
        "4. Within the database ` airbnb`, create the collection ‘listings_reviews’.\n",
        "5. Create a [vector search index](https://www.mongodb.com/docs/atlas/atlas-vector-search/create-index/#procedure/) named vector_index for the ‘listings_reviews’ collection. This index enables the RAG application to retrieve records as additional context to supplement user queries via vector search. Below is the JSON definition of the data collection vector search index.\n",
        "\n",
        "Your vector search index created on MongoDB Atlas should look like below:\n",
        "\n",
        "```\n",
        "{\n",
        "  \"fields\": [\n",
        "    {\n",
        "      \"numDimensions\": 256,\n",
        "      \"path\": \"embedding\",\n",
        "      \"similarity\": \"cosine\",\n",
        "      \"type\": \"vector\"\n",
        "    }\n",
        "  ]\n",
        "}\n",
        "\n",
        "```\n",
        "\n",
        "Follow MongoDB’s [steps to get the connection](https://www.mongodb.com/docs/manual/reference/connection-string/) string from the Atlas UI. After setting up the database and obtaining the Atlas cluster connection URI, securely store the URI within your development environment.\n",
        "\n",
        "This guide uses Google Colab, which offers a feature for securely storing environment secrets. These secrets can then be accessed within the development environment. Specifically, the line mongo_uri = userdata.get('MONGO_URI') retrieves the URI from the secure storage."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "metadata": {
        "id": "ohPva919S2fx"
      },
      "outputs": [],
      "source": [
        "os.environ[\"MONGO_URI\"] = \"\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "iCqflLPNBZe4",
        "outputId": "8a7b0e30-f38b-49e7-fbf9-8d3936ea3e3e"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Connection to MongoDB successful\n"
          ]
        }
      ],
      "source": [
        "import pymongo\n",
        "\n",
        "\n",
        "def get_mongo_client(mongo_uri):\n",
        "    \"\"\"Establish and validate connection to the MongoDB.\"\"\"\n",
        "\n",
        "    client = pymongo.MongoClient(\n",
        "        mongo_uri, appname=\"devrel.showcase.openai_llamaindex_agent\"\n",
        "    )\n",
        "\n",
        "    # Validate the connection\n",
        "    ping_result = client.admin.command(\"ping\")\n",
        "    if ping_result.get(\"ok\") == 1.0:\n",
        "        # Connection successful\n",
        "        print(\"Connection to MongoDB successful\")\n",
        "        return client\n",
        "    print(\"Connection to MongoDB failed\")\n",
        "    return None\n",
        "\n",
        "\n",
        "mongo_uri = os.environ.get(\"MONGO_URI\")\n",
        "if not mongo_uri:\n",
        "    print(\"MONGO_URI not set in environment variables\")\n",
        "\n",
        "mongo_client = get_mongo_client(mongo_uri)\n",
        "\n",
        "DB_NAME = \"airbnb\"\n",
        "COLLECTION_NAME = \"listings_reviews\"\n",
        "\n",
        "db = mongo_client.get_database(DB_NAME)\n",
        "collection = db.get_collection(COLLECTION_NAME)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "D5sne8YMBa80",
        "outputId": "9399651f-aa66-4cd9-870f-f21fed16035f"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "DeleteResult({'n': 0, 'electionId': ObjectId('7fffffff0000000000000029'), 'opTime': {'ts': Timestamp(1719315234, 1), 't': 41}, 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1719315234, 1), 'signature': {'hash': b\"\\x11T\\xcc'\\xfd\\xd5\\x90@\\x0f\\xac%Z\\x13\\xc2\\xf9t4B:h\", 'keyId': 7320226449804230662}}, 'operationTime': Timestamp(1719315234, 1)}, acknowledged=True)"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# To ensure we are working with a fresh collection\n",
        "# delete any existing records in the collection\n",
        "collection.delete_many({})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HGL7X16WzaUJ"
      },
      "source": [
        "## Data Ingestion"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aj4M9doOBc9f"
      },
      "outputs": [],
      "source": [
        "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n",
        "\n",
        "vector_store = MongoDBAtlasVectorSearch(\n",
        "    mongo_client,\n",
        "    db_name=DB_NAME,\n",
        "    collection_name=COLLECTION_NAME,\n",
        "    index_name=\"vector_index\",\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "JnoeKB7uLdx1"
      },
      "outputs": [],
      "source": [
        "vector_store.add(nodes)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZqjMKHMizlOM"
      },
      "source": [
        "## Creating Retriver Tool for Agent"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "metadata": {
        "id": "s9mKDlRSBe3J"
      },
      "outputs": [],
      "source": [
        "from llama_index.core import VectorStoreIndex\n",
        "from llama_index.core.tools import QueryEngineTool, ToolMetadata\n",
        "\n",
        "index = VectorStoreIndex.from_vector_store(vector_store)\n",
        "query_engine = index.as_query_engine(similarity_top_k=5, llm=llm)\n",
        "\n",
        "query_engine_tool = QueryEngineTool(\n",
        "    query_engine=query_engine,\n",
        "    metadata=ToolMetadata(\n",
        "        name=\"knowledge_base\",\n",
        "        description=(\n",
        "            \"Provides information about Airbnb listings and reviews.\"\n",
        "            \"Use a detailed plain text question as input to the tool.\"\n",
        "        ),\n",
        "    ),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GyCMYLAB1ifQ"
      },
      "source": [
        "## AI Agent Creation"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "metadata": {
        "id": "HTdNtlWE1h36"
      },
      "outputs": [],
      "source": [
        "from llama_index.core.agent import FunctionCallingAgentWorker\n",
        "\n",
        "agent_worker = FunctionCallingAgentWorker.from_tools(\n",
        "    [query_engine_tool], llm=llm, verbose=True\n",
        ")\n",
        "agent = agent_worker.as_agent()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "8s-juQ03BgjA",
        "outputId": "ede0c4bb-6f08-4424-b7ff-5537bf171aee"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Added user message to memory: Tell me the best listing for a place in New York\n",
            "=== LLM Response ===\n",
            "Certainly! To provide you with the best listing for a place in New York, I'll need to use the knowledge base tool to gather information about Airbnb listings in New York. Let me do that for you.\n",
            "=== Calling Function ===\n",
            "Calling function: knowledge_base with args: {\"input\": \"What is the best Airbnb listing in New York City? Please provide details about its location, amenities, price, and guest reviews.\"}\n",
            "=== Function Output ===\n",
            "While it's difficult to definitively say which is the \"best\" Airbnb listing in New York City, as preferences can vary, one standout option appears to be the newly renovated studio apartment in Midtown East Manhattan. \n",
            "\n",
            "This luxurious studio is located in the heart of Manhattan, in a safe residential area that's very close to many attractions. It's just a 7-minute walk to the subway and 2 blocks from the United Nations.\n",
            "\n",
            "The apartment was completely renovated in 2016 and features modern amenities including:\n",
            "- A new kitchen with stainless steel appliances\n",
            "- A new bathroom with a rain shower\n",
            "- Hardwood floors\n",
            "- A queen-size pillow top mattress\n",
            "- Full cable TV and WiFi\n",
            "- Air conditioning\n",
            "- A HEPA air purifier for improved air quality\n",
            "\n",
            "It can accommodate up to 4 guests with its queen bed and a double sofa bed. The price is $239 per night, with a $15 charge for each additional guest beyond the first two.\n",
            "\n",
            "Guest reviews for this property are exceptional. It has received perfect 10/10 scores for accuracy, cleanliness, check-in, communication, location, and value. The overall rating is an impressive 98 out of 100, based on 119 reviews.\n",
            "\n",
            "This apartment seems to offer a combination of prime location, modern amenities, and consistently positive guest experiences, making it a top contender for one of the best Airbnb listings in New York City.\n",
            "=== LLM Response ===\n",
            "Based on the information from our knowledge base, I can tell you about one of the best Airbnb listings in New York City. While \"best\" can be subjective depending on individual preferences, this particular listing stands out due to its location, amenities, price, and excellent guest reviews.\n",
            "\n",
            "The standout option is a newly renovated studio apartment in Midtown East Manhattan. Here are the key details:\n",
            "\n",
            "Location:\n",
            "- Heart of Manhattan\n",
            "- Safe residential area\n",
            "- Close to many attractions\n",
            "- 7-minute walk to the subway\n",
            "- 2 blocks from the United Nations\n",
            "\n",
            "Amenities:\n",
            "- Completely renovated in 2016\n",
            "- New kitchen with stainless steel appliances\n",
            "- New bathroom with a rain shower\n",
            "- Hardwood floors\n",
            "- Queen-size pillow top mattress\n",
            "- Full cable TV and WiFi\n",
            "- Air conditioning\n",
            "- HEPA air purifier\n",
            "\n",
            "Capacity and Price:\n",
            "- Accommodates up to 4 guests\n",
            "- Queen bed and a double sofa bed\n",
            "- $239 per night\n",
            "- $15 charge for each additional guest beyond the first two\n",
            "\n",
            "Guest Reviews:\n",
            "- Perfect 10/10 scores for accuracy, cleanliness, check-in, communication, location, and value\n",
            "- Overall rating of 98 out of 100 based on 119 reviews\n",
            "\n",
            "This listing offers a great combination of a prime location in Manhattan, modern amenities due to its recent renovation, and consistently positive guest experiences. The perfect scores across various categories and the high overall rating suggest that guests have been very satisfied with their stays.\n",
            "\n",
            "The price point of $239 per night is competitive for a well-appointed studio in such a central location in New York City, especially considering the high-quality amenities and positive reviews.\n",
            "\n",
            "Would you like more information about this listing or are you interested in exploring other options in New York City?\n",
            "Based on the information from our knowledge base, I can tell you about one of the best Airbnb listings in New York City. While \"best\" can be subjective depending on individual preferences, this particular listing stands out due to its location, amenities, price, and excellent guest reviews.\n",
            "\n",
            "The standout option is a newly renovated studio apartment in Midtown East Manhattan. Here are the key details:\n",
            "\n",
            "Location:\n",
            "- Heart of Manhattan\n",
            "- Safe residential area\n",
            "- Close to many attractions\n",
            "- 7-minute walk to the subway\n",
            "- 2 blocks from the United Nations\n",
            "\n",
            "Amenities:\n",
            "- Completely renovated in 2016\n",
            "- New kitchen with stainless steel appliances\n",
            "- New bathroom with a rain shower\n",
            "- Hardwood floors\n",
            "- Queen-size pillow top mattress\n",
            "- Full cable TV and WiFi\n",
            "- Air conditioning\n",
            "- HEPA air purifier\n",
            "\n",
            "Capacity and Price:\n",
            "- Accommodates up to 4 guests\n",
            "- Queen bed and a double sofa bed\n",
            "- $239 per night\n",
            "- $15 charge for each additional guest beyond the first two\n",
            "\n",
            "Guest Reviews:\n",
            "- Perfect 10/10 scores for accuracy, cleanliness, check-in, communication, location, and value\n",
            "- Overall rating of 98 out of 100 based on 119 reviews\n",
            "\n",
            "This listing offers a great combination of a prime location in Manhattan, modern amenities due to its recent renovation, and consistently positive guest experiences. The perfect scores across various categories and the high overall rating suggest that guests have been very satisfied with their stays.\n",
            "\n",
            "The price point of $239 per night is competitive for a well-appointed studio in such a central location in New York City, especially considering the high-quality amenities and positive reviews.\n",
            "\n",
            "Would you like more information about this listing or are you interested in exploring other options in New York City?\n"
          ]
        }
      ],
      "source": [
        "response = agent.chat(\"Tell me the best listing for a place in New York\")\n",
        "print(str(response))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "iLvSnEysqdbP"
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {}
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
